﻿using AlOss;
using com.nm;
using com.nm.ApiServer;
using com.nm.ApiServer.Attributes;
using com.nm.Attributes;
using com.nm.db.Models.Systems;
using com.nm.Helper;
using EntityFramework.Extensions;
using george.Web.Helper;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace BaseAPI
{
    public class ImageHandler : BaseHandler
    {
        readonly Dictionary<string, string> _uploadPaths = new Dictionary<string, string>(){
            { "USER" ,"~/upfile/Avatar" }
        };

        object returnKindEditor(bool succ, string txt)
        {
            if (succ)
            {
                return new
                {
                    error = 0,
                    url = txt
                };
            }
            return new
            {
                error = 1,
                message = txt
            };
        }
        /// <summary>
		/// 暂停使用
		/// </summary>
		/// <param name="basePath"></param>
		/// <returns></returns>
		[Description("实现Ajax上传和表单POST上传，上传的图片会自动按照日期存储在子目录下")]
        [ReturnType(typeof(kmImages), "如果上传了多个文件就返回一个数组")]
        public object Upload_old(
            [Description("把文件保存在那个目录下")]
            string basePath = "")
        {
            if (string.IsNullOrWhiteSpace(basePath))
                basePath = Request.Get("basePath", "");
            var isKindEditor = Request.Get("T", "") == "KindEditor";
            if (_uploadPaths.ContainsKey(basePath.ToUpper()) == false)
            {
                return isKindEditor
                    ? returnKindEditor(false, "上传目录不存在")
                    : Error("上传目录不存在", 404);
            }
            SysEntities dc = null;
            var vPath = _uploadPaths[basePath.ToUpper()] + "/" + DateTime.Now.ToString("yyyyMMdd");
            //var path = Server.MapPath(vPath);
            var serverPath = ConfigurationHelper.Get("UpfilePath", @"E:\filemanager\site\release");
            var path = serverPath + vPath.Substring(1);
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            var imgList = new List<kmImages>();
            if (this.Request.Headers.AllKeys.Contains("X_FILENAME") && this.Request.Headers["X_FILENAME"] == "AJAX")
            {
                var length = Request.ContentLength;
                Request.InputStream.Seek(0, SeekOrigin.Begin);
                var bytes = Request.BinaryRead(length);
                var name = DateTime.Now.Ticks + ".jpg";
                var toSave = Path.Combine(path, name);
                File.WriteAllBytes(toSave, bytes);
                var img = new kmImages()
                {
                    ID = Guid.NewGuid(),
                    Title = Request.Get("fn", name),
                    Url = $"{vPath}/{name}"
                };
                if (SaveImg(ref dc, img))
                {
                    imgList.Add(img);
                }
            }
            else
            {
                for (var i = 0; i < Request.Files.Count; i++)
                {
                    var postFile = Request.Files[i];
                    var name = DateTime.Now.Ticks + ".jpg";
                    var toSave = Path.Combine(path, name);
                    postFile.SaveAs(toSave);
                    var img = new kmImages()
                    {
                        ID = Guid.NewGuid(),
                        Title = postFile.FileName,
                        Url = $"{vPath}/{name}"
                    };
                    if (SaveImg(ref dc, img))
                    {
                        imgList.Add(img);
                    }
                }
            }
            foreach (var img in imgList)
            {
                img.Url = this.GetImageUrl(Request.ResolveClientUrl(img.Url));
            }
            if (isKindEditor)
            {
                return imgList.Count == 0
                    ? returnKindEditor(false, "上传失败")
                    : returnKindEditor(true, imgList[0].Url);
            }
            switch (imgList.Count)
            {
                case 0:
                    return Error("上传失败");
                case 1:
                    return Success(imgList[0]);
                default:
                    return Success(imgList);
            }
        }

        [MustLogin]
        [Description("上传到图片")]
        [ReturnType(typeof(IList<kmImages>))]
        public ApiResult Upload([ParamDescription("保存地址")]string basePath = "")
        {
            if (Request.Get("T", "") == "KindEditor")
            {
                return Error("KindEditor上传请使用：Image.UploadKind");
            }
            if (string.IsNullOrWhiteSpace(basePath))
                basePath = Request.Get("basePath", "");

            if (this.GetConfiguration("use-oss", false))
            {
                return UploadToOss(basePath);
            }
            if (_uploadPaths.ContainsKey(basePath.ToUpper()) == false)
            {
                return Error("上传目录不存在", 404);
            }
            SysEntities dc = null;
            var vPath = _uploadPaths[basePath.ToUpper()] + "/" + DateTime.Now.ToString("yyyyMMdd");
            var serverPath = ConfigurationHelper.Get("UpfilePath", @"E:\filemanager\site\release");
            var path = serverPath + vPath.Substring(1);
            //var path = Server.MapPath(vPath);
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            var imgList = new List<kmImages>();
            //Log.WriteLines(
            //    "xxxxxxxxxxxxxxxxxx",
            //    Request.QueryString.ToString(),
            //    Request.ContentType,
            //    Request.ContentLength,
            //    this.Request.Get("X_FILENAME", ""),
            //    (this.Request.Headers.AllKeys.Contains("X_FILENAME") && this.Request.Headers["X_FILENAME"] == "AJAX")
            //    || this.Request.Get("X_FILENAME", "") == "AJAX"
            //    );
            if ((this.Request.Headers.AllKeys.Contains("X_FILENAME") && this.Request.Headers["X_FILENAME"] == "AJAX")
                || this.Request.Get("X_FILENAME", "") == "AJAX")
            {
                var length = Request.ContentLength;
                Request.InputStream.Seek(0, SeekOrigin.Begin);
                var bytes = Request.BinaryRead(length);
                var name = DateTime.Now.Ticks + ".jpg";
                var toSave = Path.Combine(path, name);
                File.WriteAllBytes(toSave, bytes);
                var img = new kmImages()
                {
                    ID = Guid.NewGuid(),
                    Title = Request.Get("fn", name),
                    Url = $"{vPath}/{name}"
                };
                if (SaveImg(ref dc, img))
                {
                    imgList.Add(img);
                }
            }
            else
            {
                for (var i = 0; i < Request.Files.Count; i++)
                {
                    var postFile = Request.Files[i];
                    var name = DateTime.Now.Ticks + ".jpg";
                    var toSave = Path.Combine(path, name);
                    postFile.SaveAs(toSave);
                    var img = new kmImages()
                    {
                        ID = Guid.NewGuid(),
                        Title = postFile.FileName,
                        Url = $"{vPath}/{name}"
                    };
                    if (SaveImg(ref dc, img))
                    {
                        imgList.Add(img);
                    }
                }
            }
            foreach (var img in imgList)
            {
                img.Url = this.GetImageUrl(Request.ResolveClientUrl(img.Url));
            }

            switch (imgList.Count)
            {
                case 0:
                    return Error("上传失败");
                case 1:
                    return Success(imgList[0]);
                default:
                    return Success(imgList);
            }
        }
        /// <summary>
        /// 根据图片ID获取图片地址
        /// </summary>
        /// <param name="ID"></param>
        /// <param name="Mode"></param>
        /// <param name="Style"></param>
        /// <param name="Protocol"></param>
        /// <param name="Type"></param>
        /// <returns></returns>
        [Description("根据图片ID获取图片地址")]
        public ApiResult Show(
            [Description("图片ID")]
            Guid ID,
            [Description("预制的图片格式（尺寸、缩放方式等等），空表示使用原图 -- 未实现")]
            string Mode = "",
            [Description("代表需要一张宽（w）100px、高（h）100px、绝对质量（Q）90%、jpg格式的图片，空表示使用原图，Mode参数优先！ -- 未实现")]
            string Style = "",
            [Description("协议，空或者无法识别则使用默认设置（一般是http) -- 未实现")]
            string Protocol = "http",
            [Description("返回的数据格式，0-标准格式，1-url字符串。 -- 未实现")]
            int Type = 0)
        {
            using (var dc = new SysEntities())
            {
                var img = dc.kmImages.FirstOrDefault(i => i.ID == ID);
                if (img == null)
                    return Error("图片不存在", 404);
                return Success(this.GetImageUrl(Request.ResolveClientUrl(img.Url), Protocol));
            }
        }
        /// <summary>
        /// 删除图片
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Description("删除图片")]
        [ReturnType(typeof(string), "成功返回 OK")]
        public ApiResult Remove(
            [ParamDescription("要删除的图片ID")]
            Guid id)
        {
            using (var dc = new SysEntities())
            {
                var img = dc.kmImages.FirstOrDefault(i => i.ID == id);
                if (img == null)
                    return Error("图片不存在", 404);
                dc.kmImages.Where(i => i.ID == img.ID).Delete();
                try
                {
                    dc.SaveChanges();
                }
                catch (Exception ex)
                {
                    return Error(ex);
                }
                if (!string.IsNullOrWhiteSpace(img.BucketName))
                {
                    var oss = OssHelper.GetClient(img.BucketName);
                    oss.DeleteObject(img.Url);
                    return Success("OK");
                }
                if (!img.Url.StartsWith("~/") && !img.Url.StartsWith("/"))
                    return Success("OK");
                var fileToDel = img.Url.StartsWith("/")
                    ? img.Url
                    : Server.MapPath(img.Url);
                try
                {
                    File.Delete(fileToDel);
                }
                catch (FileNotFoundException ex)
                {
                    Log.Error(ex);
                }
                catch (Exception ex)
                {
                    return Error(ex);
                }
                return Success("OK");
            }
        }
        /// <summary>
        /// 删除图片
        /// </summary>
        /// <param name="id"></param>
        /// <param name="dc"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public static bool RemoveImage(Guid id, SysEntities dc, HttpServerUtility server)
        {
            var img = dc.kmImages.FirstOrDefault(i => i.ID == id);
            if (img == null)
                return false;
            dc.kmImages.Where(i => i.ID == img.ID).Delete();
            try
            {
                dc.SaveChanges();
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
            if (!img.Url.StartsWith("~/") && !img.Url.StartsWith("/")) return true;
            var fileToDel = img.Url.StartsWith("/")
                ? img.Url
                : server.MapPath(img.Url);
            try
            {
                File.Delete(fileToDel);
            }
            catch (FileNotFoundException ex)
            {
                Log.Error(ex);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
            return true;
        }

        static bool SaveImg(ref SysEntities dc, kmImages img)
        {
            if (dc == null)
            {
                using (dc = new SysEntities())
                {
                    return SaveImg(ref dc, img);
                }
            }
            dc.kmImages.Add(img);
            try
            {
                dc.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                return false;
            }
        }

        [Description("上传到图片到OSS服务器（根据配置）")]
        [ReturnType(typeof(IList<kmImages>))]
        public ApiResult UploadToOss([ParamDescription("保存地址")]string basePath = "")
        {
            if (string.IsNullOrWhiteSpace(basePath))
                basePath = Request.Get("basePath", "");
            var vPath = (_uploadPaths[basePath.ToUpper()] + "/" + DateTime.Now.ToString("yyyyMMdd")).Substring(9);
            var BucketName = this.GetConfiguration("image-oss-BucketName", "");
            var oss = OssHelper.GetClient(BucketName);
            var dc = new SysEntities();
            var imgList = new List<kmImages>();
            if ((this.Request.Headers.AllKeys.Contains("X_FILENAME") && this.Request.Headers["X_FILENAME"] == "AJAX")
                || this.Request.Get("X_FILENAME", "") == "AJAX")
            {
                var length = Request.ContentLength;
                Request.InputStream.Seek(0, SeekOrigin.Begin);
                var bytes = Request.BinaryRead(length);
                var name = DateTime.Now.Ticks.ToString();
                var toSave = getFileName(vPath, Request.Get("fn", name));
                //var toSave = vPath + name;
                oss.UploadDataAsync(toSave, bytes);
                var img = new kmImages()
                {
                    ID = Guid.NewGuid(),
                    Title = Request.Get("fn", name),
                    Url = toSave,
                    BucketName = BucketName
                };
                if (SaveImg(ref dc, img))
                {
                    imgList.Add(img);
                }
            }
            else
            {
                for (var i = 0; i < Request.Files.Count; i++)
                {
                    var postFile = Request.Files[i];
                    var name = DateTime.Now.Ticks.ToString();
                    //var toSave = vPath + name;
                    var toSave = getFileName(vPath, postFile);
                    byte[] data = new byte[postFile.InputStream.Length];
                    postFile.InputStream.Read(data, 0, (int)postFile.InputStream.Length);
                    oss.UploadDataAsync(toSave, data);

                    //oss.UploadDataAsync(toSave, postFile.InputStream);
                    var img = new kmImages()
                    {
                        ID = Guid.NewGuid(),
                        Title = postFile.FileName,
                        Url = toSave,
                        BucketName = BucketName
                    };
                    if (SaveImg(ref dc, img))
                    {
                        imgList.Add(img);
                    }
                }
            }
            foreach (var img in imgList)
            {
                img.Url = oss.GetImageUrl(img.Url);
            }

            switch (imgList.Count)
            {
                case 0:
                    return Error("上传失败");
                case 1:
                    return Success(imgList[0]);
                default:
                    return Success(imgList);
            }
        }


        [Description("保存OSS服务器图片，APP（或者其他客户端）自行上传到OSS服务器，然后使用此API保存相关信息")]
        [ReturnType(typeof(kmImages), "OSS地址请自行拼接")]
        public ApiResult SaveOss(
            [ParamDescription("图片名称，如果空自动使用“key”")]string ImageName,
            [ParamDescription("OSS BucketName")]string BucketName,
            [ParamDescription("key")]string Key)
        {

            if (string.IsNullOrWhiteSpace(BucketName))
            {
                return Error("BucketName 不能为空");
            }
            if (string.IsNullOrWhiteSpace(Key))
            {
                return Error("Key 不能为空");
            }
            if (!OssHelper.BucketExist(BucketName))
            {
                return Error("BucketName 不存在");
            }
            if (!OssHelper.ObjectExist(BucketName, Key))
            {
                return Error("BucketName 不存在");
            }
            var img = new kmImages()
            {
                ID = Guid.NewGuid(),
                Title = string.IsNullOrWhiteSpace(ImageName) ? Key : ImageName,
                Url = Key,
                BucketName = BucketName,
            };
            var dc = new SysEntities();
            dc.kmImages.Add(img);
            try
            {
                dc.SaveChanges();
            }
            catch (
               Exception ex
               )
            {
                return Error(ex);
            }
            img.Url = getOssUrl(img);
            return Success(img);
        }

        static string getOssUrl(kmImages img)
        {
            if (string.IsNullOrWhiteSpace(img.BucketName))
                return img.Url;
            return OssHelper.GetImageUrl(img.BucketName, img.Url);
        }

        private static string getFileName(string vPath, string fileName)
        {
            if (fileName.Contains("."))
            {
                var name = DateTime.Now.Ticks.ToString();
                var ss = fileName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                return $"{vPath}/{name}.{ss.LastOrDefault()}";
            }
            return $"{vPath}/{fileName}".Replace("//", "/"); ;
        }

        private static string getFileName(string vPath, HttpPostedFile postFile)
        {
            var name = DateTime.Now.Ticks.ToString();
            var ss = postFile.FileName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            return $"{vPath}/{name}.{ss.LastOrDefault()}".Replace("//", "/");
        }
    }
}
